package com.ruan.quartz;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.ruan.mapper.*;
import com.ruan.pojo.*;
import com.ruan.utils.DateUtils;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.springframework.scheduling.quartz.QuartzJobBean;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.sql.Date;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;

public class SalaryQuartz extends QuartzJobBean {

    @Resource
    private SalaryMapper salaryMapper;

    @Resource
    private MonthCountMapper monthCountMapper;

    @Resource
    private BusinessTripMapper businessTripMapper;

    @Resource
    private EmployeeMapper employeeMapper;

    @Resource
    private OnDutySalarySetMapper onDutySalarySetMapper;


    @Resource
    private SalarySetMapper salarySetMapper;
//定时发工资
    @Override
    protected void executeInternal(JobExecutionContext context) throws JobExecutionException {
        //创建一个Date对象month，表示当前时间，通过System.currentTimeMillis()获取。
        Date month = new Date(System.currentTimeMillis());
        System.out.println("哪个month定时发工资："+month);
        //然后创建一个Calendar对象calendar，并将当前时间设置为month所表示的时间。
        Calendar calendar = Calendar.getInstance();//获取当前系统时间
        System.out.println("calendar是："+calendar);
        calendar.setTime(month);//将calendar对象的时间设置为month所表示的时间。
        // 这样就实现了将Date对象的时间转换为Calendar对象的时间

        //表示将当前日期的月份减去1个月,得到上一个月的时间
        calendar.add(Calendar.MONTH,-1);//生成的是上个月的工资
        //在当前日期的基础上不做任何月份的增减，即保持当前日期不变
//        calendar.add(Calendar.MONTH,0);//生成的是本月的工资
        //创建一个SimpleDateFormat对象sdf，用于将日期格式化为"yyyy-MM"的形式。
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM");
        System.out.println("sdf是:"+sdf);
        //创建另一个SimpleDateFormat对象sdf2，用于将日期格式化为"yyyy-MM-01"的形式。
        SimpleDateFormat sdf2 = new SimpleDateFormat("yyyy-MM-01");
        System.out.println("sdf2是:"+sdf2);
        //使用sdf.format(calendar.getTime())将上一个月的时间格式化为"yyyy-MM"，
        // 存储在lastMonth中，表示上一个月的月份，例如"2024-03"。
        String lastMonth = sdf.format(calendar.getTime());//本月的上个月 2024-03
        System.out.println("lastMonth是："+lastMonth);
        //使用sdf2.format(calendar.getTime())将上一个月的时间格式化为"yyyy-MM-01"，
        // 存储在firstDay中，表示上一个月的第一天，例如"2024-03-01"。
        String firstDay = sdf2.format(calendar.getTime());//上个月的第一天 2024-03-01
//用于计算上一个月的出差的天数
        //调用DateUtils.getLastDay(firstDay)获取上一个月的最后一天，存储在lastDay中，例如"2024-03-30"。
        String lastDay = DateUtils.getLastDay(firstDay);//上个月的最后一天 2024-03-30

        //传入null作为参数是告诉onDutySalarySetMapper.selectOne方法不需要任何条件来过滤查询结果，
        // 即返回表中的第一条记录（通常是按照数据库的默认顺序）。这样做可以用来获取表中的任意一条记录，
        // 而不需要指定具体的查询条件。
        OnDutySalarySet onDutySalarySet = onDutySalarySetMapper.selectOne(null);

        //获取管理员设置的奖惩制度
        BigDecimal overTimeSubsidy = onDutySalarySet.getOverTimeSubsidy();//每小时加班补助
        BigDecimal awayWorkLess = onDutySalarySet.getAwayWorkLess();//旷工扣除
        BigDecimal leaveLess = onDutySalarySet.getLeaveLess();//请假扣除
        BigDecimal lateLess = onDutySalarySet.getLateLess();//迟到扣除
        BigDecimal earlyLess = onDutySalarySet.getEarlyLess();//早退扣除

        LambdaQueryWrapper<Employee> queryWrapper = new LambdaQueryWrapper<>();
        //除开离职和待审核的员工
        queryWrapper.ne(Employee::getStatus,"离职")
                .ne(Employee::getStatus,"待审核");
        //所有要发工资的人
        List<Employee> employeeList = employeeMapper.selectList(queryWrapper);

        List<String> phoneList = new ArrayList<>();
        for (Employee employee : employeeList) {
            phoneList.add(employee.getPhone());
            System.out.println("在职的每个员工的手机号："+employee.getPhone());
        }

        for (String phone : phoneList) {
            LambdaQueryWrapper<SalarySet> salarySetWrapper = new LambdaQueryWrapper<>();
            LambdaQueryWrapper<Employee> queryWrapper1 = new LambdaQueryWrapper<>();
            queryWrapper1.eq(Employee::getPhone,phone);
            Employee employee1 = employeeMapper.selectOne(queryWrapper1);
            salarySetWrapper.eq(SalarySet::getEmployeeId,employee1.getId());

            SalarySet salarySet = salarySetMapper.selectOne(salarySetWrapper);
            System.out.println("salarySet是"+salarySet);

            BigDecimal basicSalary = BigDecimal.valueOf(0);//基本工资
            BigDecimal trafficSubsidy = BigDecimal.valueOf(0);//交通补助
            BigDecimal mealsSubsidy = BigDecimal.valueOf(0);//餐饮补助

            if(salarySet!=null){//查不到该员工的调薪记录
                //throw new BusinessException(Code.SELECT_OK,"该员工薪资设置查询失败！");
                basicSalary = salarySet.getBasicSalary();//基本工资
                trafficSubsidy = salarySet.getTrafficSubsidy();//交通补助
                mealsSubsidy = salarySet.getMealsSubsidy();//餐饮补助
             }
            //需要用到monthCount(每月统计表)表的数据计算工资
            LambdaQueryWrapper<MonthCount> monthCountWrapper = new LambdaQueryWrapper<>();
            monthCountWrapper.eq(MonthCount::getEmployeeId,employee1.getId());

            monthCountWrapper.like(MonthCount::getMonth,lastMonth);

            //理论上每个月只有一条记录生成，实际上测试的时候，可能会生成多条。以至于报错
            MonthCount monthCount = monthCountMapper.selectOne(monthCountWrapper);
            if (monthCount != null) {//能查到每月的请假天数，迟到次数，早退次数，旷工天数，加班时长，出差次数，
                Integer leaveDay = monthCount.getLeaveDay();//请假天数

                Integer lateCount = monthCount.getLateCount();//迟到次数

                Integer earlyCount = monthCount.getEarlyCount();//早退次数

                Integer awayWorkDay = monthCount.getAwayWorkDay();//旷工天数

                Integer overTimeHours = monthCount.getOverTimeHours();//加班时长

            LambdaQueryWrapper<BusinessTrip> tripWrapper = new LambdaQueryWrapper<>();

            tripWrapper.eq(BusinessTrip::getEmployeeId,employee1.getId());

            tripWrapper.eq(BusinessTrip::getStatus,"同意");//已同意的出差数
            tripWrapper.between(BusinessTrip::getBackTime,firstDay,lastDay);//上个月同意的出差天数
            List<BusinessTrip> businessTripList = businessTripMapper.selectList(tripWrapper);
            BigDecimal actualCostSum = BigDecimal.valueOf(0);//初始化出差总报销金额
            for (BusinessTrip businessTrip : businessTripList) {
                BigDecimal actualCost = businessTrip.getActualCost();//依次获取上个月每次出差获取实际花费
                if (actualCost!=null){
//                BigDecimal类型的值不能直接使用+操作符相加。
                    actualCostSum = actualCostSum.add(actualCost);
                }
            }

            Salary salary = new Salary();
            salary.setEmployeeId(monthCount.getEmployeeId());//设置员工信息

            salary.setDepartmentId(monthCount.getDepartmentId());//设置员工部门信息

            BigDecimal result1 = new BigDecimal(awayWorkDay).multiply(awayWorkLess);
            salary.setAwayWorkLess(result1);//计算旷工扣除
            BigDecimal result2 = new BigDecimal(lateCount).multiply(lateLess);
            salary.setLateLess(result2);//计算迟到扣除
            BigDecimal result3 = new BigDecimal(earlyCount).multiply(earlyLess);
            salary.setEarlyLess(result3);//计算早退扣除
            BigDecimal result4 = new BigDecimal(leaveDay).multiply(leaveLess);
            salary.setLeaveLess(result4);//计算请假扣除
            salary.setMealsSubsidy(mealsSubsidy);//餐饮补助
            salary.setTrafficSubsidy(trafficSubsidy);//交通补助
            BigDecimal result5 = new BigDecimal(String.valueOf(overTimeSubsidy)).multiply(BigDecimal.valueOf(overTimeHours));
            salary.setOverTimeSubsidy(result5);//计算加班补助
            salary.setTripSubsidy(actualCostSum);//出差报销
            //基本工资
            BigDecimal originalPay = basicSalary.add(trafficSubsidy).add(mealsSubsidy);
            salary.setOriginalPay(originalPay);
            //应发工资=基本工资+交通补+伙食补

            //实发工资=原始工资+加班工资+出差报销-迟到/早退/请假/旷工扣除
                BigDecimal actualPay = salary.getOriginalPay()
                        .add(salary.getOverTimeSubsidy())
                        .add(salary.getTripSubsidy())
                        .subtract(salary.getLateLess())
                        .subtract(salary.getEarlyLess())
                        .subtract(salary.getLeaveLess())
                        .subtract(salary.getAwayWorkLess());

                salary.setActualPay(actualPay);

            salary.setMonth(lastMonth);//设置发放工资的月份
            salary.setStatus("未发放");//待审核
            salaryMapper.insert(salary);
        }
        }
    }
}
